package com.witmore.neutron.ai.web.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jk.common.response.ResponseResult;
import com.witmore.neutron.ai.api.enums.ChatClientType;
import com.witmore.neutron.ai.db.entity.AgentDO;
import com.witmore.neutron.ai.db.entity.AgentPublishConfigDO;
import com.witmore.neutron.ai.db.entity.ModelConfigDO;
import com.witmore.neutron.ai.db.mapper.AgentMapper;
import com.witmore.neutron.ai.db.mapper.AgentPublishConfigMapper;
import com.witmore.neutron.ai.db.mapper.ModelConfigMapper;
import com.witmore.neutron.ai.web.apiv2.controller.vo.ProviderEmployeeResult;
import com.witmore.neutron.ai.web.controller.vo.*;
import com.witmore.neutron.ai.web.enums.PublishTypeEnum;
import com.witmore.neutron.ai.web.filter.GlobalAccountSession;
import com.witmore.neutron.ai.web.service.RobotService;
import com.witmore.neutron.ai.web.utils.RandomCodeGenerator;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Random;

/**
 * Description: RobotServiceImpl
 * Author: 豆子高
 * Date: 2025/5/19 17:14
 */
@Service
public class RobotServiceImpl implements RobotService {

    @Autowired
    private AgentMapper agentMapper;

    @Autowired
    private ModelConfigMapper modelConfigMapper;

    @Autowired
    private AgentPublishConfigMapper agentPublishConfigMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult<Void> createRobot(AgentCreateParam param) {
        // 重名校验
        AgentDO agent = agentMapper.selectOne(new LambdaQueryWrapper<AgentDO>()
                .eq(AgentDO::getAgentName, param.getAgentName())
                .eq(AgentDO::getUserId, GlobalAccountSession.getUserInfo().getId()));
        if (agent != null) {
            return ResponseResult.fail(1001, "机器人名称已存在");
        }
        AgentDO agentDO = new AgentDO();
        agentDO.setAgentCode(this.generateAndCheckAgentCode());
        agentDO.setAgentName(param.getAgentName());
        agentDO.setUserId(GlobalAccountSession.getUserInfo().getId());
        agentDO.setWelcomeMsg("我是您的AI助手，请问有什么能帮您？");
        // ai模型默认取第一个
        List<ModelConfigDO> modelConfigDOS = modelConfigMapper.selectList(new LambdaQueryWrapper<ModelConfigDO>()
                .eq(ModelConfigDO::getEnabled, true)
        );
        agentDO.setAiModelId(modelConfigDOS.get(0).getId());
        agentDO.setAiModelName(modelConfigDOS.get(0).getModelName());
        agentDO.setUpdateTime(LocalDateTime.now());
        agentDO.setCreateTime(LocalDateTime.now());
        // 默认取当前用户
        ProviderEmployeeResult providerProfile = GlobalAccountSession.getUserInfo().getProviderProfile();
        agentDO.setProviderId(providerProfile == null ? null : providerProfile.getProviderId());
        agentMapper.insert(agentDO);
        // 发布表同步保存 -- Web模式
        agentPublishConfigMapper.insert(new AgentPublishConfigDO()
                .setAgentId(agentDO.getId())
                .setAgentCode(agentDO.getAgentCode())
                .setPublishType(0)
                .setPublishUrl("/chat/" + agentDO.getAgentCode())
                .setPublishStatus((byte) 0)
                .setUpdateTime(LocalDateTime.now())
                .setCreateTime(LocalDateTime.now())
        );
        // 发布表同步保存 -- API模式
        agentPublishConfigMapper.insert(new AgentPublishConfigDO()
                .setAgentId(agentDO.getId())
                .setAgentCode(agentDO.getAgentCode())
                .setPublishType(1)
                .setPublishUrl("/v1/api/chat/completions?code=%s" + agentDO.getAgentCode())
                .setPublishStatus((byte) 0)
                // TODO
                .setPublishKey("sk-" + System.currentTimeMillis())
                .setUpdateTime(LocalDateTime.now())
                .setCreateTime(LocalDateTime.now())
        );
        return ResponseResult.success();
    }

    @NotNull
    private String generateAndCheckAgentCode() {
        String agentCode = RandomCodeGenerator.generateRandomCode(16);
        // 校验agentCode全局唯一性 若是重复了 重试2次之后抛出异常
        for (int i = 0; i < 3; i++) {
            AgentDO existingAgent = agentMapper.selectOne(new LambdaQueryWrapper<AgentDO>()
                    .eq(AgentDO::getAgentCode, agentCode));
            if (existingAgent == null) {
                break;
            }
            agentCode = RandomCodeGenerator.generateRandomCode(16);
        }
        return agentCode;
    }

    @Override
    public List<AgentResult> list(RobotQueryParam robotQueryParam) {
        List<AgentDO> agentDOS = agentMapper.selectList(new LambdaQueryWrapper<AgentDO>()
                .eq(StringUtils.isNotEmpty(robotQueryParam.getAgentName()), AgentDO::getAgentName, robotQueryParam.getAgentName())
                .eq(AgentDO::getUserId, GlobalAccountSession.getUserInfo().getId())
                .orderByDesc(AgentDO::getIsLocked)
                .orderByDesc(AgentDO::getCreateTime)
        );
        if (CollectionUtils.isEmpty(agentDOS)) {
            return List.of();
        }
        return agentDOS.stream().map(agentDO -> {
            AgentResult agentResult = new AgentResult();
            BeanUtils.copyProperties(agentDO, agentResult);
            agentResult.setLocked(agentDO.getIsLocked() != null && agentDO.getIsLocked() == 1);
            // 发布信息
            AgentPublishConfigDO agentPublishConfigDO = agentPublishConfigMapper.selectOne(new LambdaQueryWrapper<AgentPublishConfigDO>()
                    .eq(AgentPublishConfigDO::getAgentId, agentDO.getId())
                    .eq(AgentPublishConfigDO::getPublishType, 0)
            );
            if (agentPublishConfigDO != null) {
                agentResult.setWebPublishStatus(agentPublishConfigDO.getPublishStatus());
            }
            return agentResult;
        }).toList();
    }

    @Override
    public AgentDO getAgentById(Long id) {
        return agentMapper.selectById(id);
    }

    @Override
    public AgentDO getAgentByCode(String agentCode) {
        return agentMapper.selectOne(new LambdaQueryWrapper<AgentDO>()
                .eq(AgentDO::getAgentCode, agentCode));
    }

    @Override
    public ResponseResult<List<ModelConfigDO>> getModels() {
        // TODO 目前 有两类 OpenAi和Others   先默认只取OpenAi的
        return ResponseResult.success(modelConfigMapper.selectList(new LambdaQueryWrapper<ModelConfigDO>()
                .eq(ModelConfigDO::getEnabled, true)
                .eq(ModelConfigDO::getChatClientType, ChatClientType.OpenAi)));

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResponseResult<Void> update(RobotUpdateParam param) {
        AgentDO agentDO = agentMapper.selectById(param.getAgentId());
        if (agentDO == null) {
            return ResponseResult.fail(1001, "机器人不存在");
        }
        // 智能体被锁定
        if (agentDO.getIsLocked() != null && agentDO.getIsLocked() == 1) {
            return ResponseResult.fail(1001, "机器人被锁定，无法更新信息，请先解锁");
        }
        // 重名校验
        AgentDO agent = agentMapper.selectOne(new LambdaQueryWrapper<AgentDO>()
                .eq(AgentDO::getAgentName, param.getAgentName())
                .eq(AgentDO::getUserId, GlobalAccountSession.getUserInfo().getId()));
        if (agent != null && !agent.getId().equals(param.getAgentId())) {
            return ResponseResult.fail(1001, "机器人名称已存在");
        }
        // 更新
        agentDO.setAgentName(param.getAgentName());
        agentDO.setAgentDesc(param.getAgentDesc());
        agentDO.setAiSysPromptText(param.getAiSysPromptText());
        agentDO.setWelcomeMsg(param.getWelcomeMsg());
        agentDO.setAgentIcon(param.getAgentIcon());
        agentDO.setAiModelId(param.getAiModelId());
        agentDO.setAiModelName(param.getAiModelName());
        agentDO.setUpdateTime(LocalDateTime.now());
        agentDO.setAiConfig(param.getAiConfigStr());
        // 设置开场问题
        agentDO.setOpeningQuestionsEnabled(param.getOpeningQuestionsEnabled());
        agentDO.setOpeningQuestions(param.getOpeningQuestions());
        agentMapper.updateById(agentDO);
        // 高级配置 -  发布信息
        if (param.getConfigParam() != null && param.getConfigParam().getId() != null){
            // 校验发布信息存在性
            AgentPublishConfigDO agentPublishConfigDO = agentPublishConfigMapper.selectById(param.getConfigParam().getId());
            if (agentPublishConfigDO == null) {
                return ResponseResult.fail(1001, "发布配置不存在");
            }
            AgentPublishConfigParam publishConfigParam = param.getConfigParam();
            AgentPublishConfigDO update = new AgentPublishConfigDO();
            update.setId(publishConfigParam.getId());
            update.setUpdateTime(LocalDateTime.now());
            update.setPublishStatus(publishConfigParam.getPublishStatus());
            update.setResponseFormatPrompt(publishConfigParam.getResponseFormatPrompt());
            agentPublishConfigMapper.updateById(update);
        }
        return ResponseResult.success();
    }

    @Override
    public ResponseResult<Void> updatePublishStatus(AgentPublishConfigParam param) {
        if (param == null || param.getId() == null || param.getPublishStatus() == null) {
            return ResponseResult.fail(1001, "参数错误");
        }
        AgentPublishConfigDO agentPublishConfigDO = agentPublishConfigMapper.selectById(param.getId());
        if (agentPublishConfigDO == null) {
            return ResponseResult.fail(1001, "发布配置不存在");
        }
        AgentDO agentDO = agentMapper.selectById(agentPublishConfigDO.getAgentId());
        if (agentDO == null) {
            return ResponseResult.fail(1001, "机器人不存在");
        }
        // 智能体被锁定
        if (agentDO.getIsLocked() != null && agentDO.getIsLocked() == 1) {
            return ResponseResult.fail(1001, "机器人被锁定，无法更新发布状态，请先解锁");
        }
        // 配置一样不做修改
        if (agentPublishConfigDO.getPublishStatus().equals(param.getPublishStatus())) {
            return ResponseResult.success();
        }
        // 更新
        agentPublishConfigDO.setPublishStatus(param.getPublishStatus());
        agentPublishConfigDO.setUpdateTime(LocalDateTime.now());
        agentPublishConfigMapper.updateById(agentPublishConfigDO);
        return ResponseResult.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResponseResult<Void> deleteRobot(Integer agentId) {
        if (agentId == null) {
            return ResponseResult.fail(1001, "参数错误");
        }
        AgentDO agentDO = agentMapper.selectById(agentId);
        if (agentDO == null) {
            return ResponseResult.fail(1001, "机器人不存在");
        }
        // 智能体被锁定
        if (agentDO.getIsLocked() != null && agentDO.getIsLocked() == 1) {
            return ResponseResult.fail(1001, "机器人被锁定，无法删除，请先解锁");
        }
        // 删除机器人
        agentMapper.deleteById(agentId);
        // 发布信息也删除
        agentPublishConfigMapper.delete(new LambdaQueryWrapper<AgentPublishConfigDO>()
                .eq(AgentPublishConfigDO::getAgentId, agentId)
        );
        return ResponseResult.success();
    }

    @Override
    public ResponseResult<Void> lock(Integer agentId) {
        if (agentId == null) {
            return ResponseResult.fail(1001, "参数错误");
        }
        AgentDO agentDO = agentMapper.selectById(agentId);
        if (agentDO == null) {
            return ResponseResult.fail(1001, "机器人不存在");
        }
        // 已锁的话 不做变动
        if (agentDO.getIsLocked() != null && agentDO.getIsLocked() == 1) {
            return ResponseResult.success();
        }
        agentDO.setIsLocked((byte) 1);
        agentDO.setUpdateTime(LocalDateTime.now());
        agentMapper.updateById(agentDO);
        return ResponseResult.success();
    }

    @Override
    public ResponseResult<Void> unlock(Integer agentId) {
        if (agentId == null) {
            return ResponseResult.fail(1001, "参数错误");
        }
        AgentDO agentDO = agentMapper.selectById(agentId);
        if (agentDO == null) {
            return ResponseResult.fail(1001, "机器人不存在");
        }
        // 未锁的话 不做变动
        if (agentDO.getIsLocked() != null && agentDO.getIsLocked() == 0) {
            return ResponseResult.success();
        }
        agentDO.setIsLocked((byte) 0);
        agentDO.setUpdateTime(LocalDateTime.now());
        agentMapper.updateById(agentDO);
        return ResponseResult.success();
    }

    @Override
    public ResponseResult<Void> updateName(RobotUpdateParam param) {
        AgentDO agentDO = agentMapper.selectById(param.getAgentId());
        if (agentDO == null) {
            return ResponseResult.fail(1001, "机器人不存在");
        }
        // 智能体被锁定
        if (agentDO.getIsLocked() != null && agentDO.getIsLocked() == 1) {
            return ResponseResult.fail(1001, "机器人被锁定，无法更新信息，请先解锁");
        }
        // 重名校验
        AgentDO agent = agentMapper.selectOne(new LambdaQueryWrapper<AgentDO>()
                .eq(AgentDO::getAgentName, param.getAgentName())
                .eq(AgentDO::getUserId, GlobalAccountSession.getUserInfo().getId()));
        if (agent != null && !agent.getId().equals(param.getAgentId())) {
            return ResponseResult.fail(1001, "机器人名称已存在");
        }
        // 更新
        agentDO.setAgentName(param.getAgentName());
        agentDO.setUpdateTime(LocalDateTime.now());
        agentMapper.updateById(agentDO);
        return ResponseResult.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResponseResult<Void> copy(Integer agentId) {
        AgentDO agentDO = agentMapper.selectById(agentId);
        if (agentDO == null) {
            return ResponseResult.fail(1001, "机器人不存在");
        }
        // 新机器人
        AgentDO newAgentDO = new AgentDO();
        newAgentDO.setAgentCode(this.generateAndCheckAgentCode());
        newAgentDO.setUserId(agentDO.getUserId());
        newAgentDO.setAgentIcon(agentDO.getAgentIcon());
        // 0000 ~ 9999
        Random random = new Random();
        String randomStr = String.format("%04d", random.nextInt(10000));
        newAgentDO.setAgentName(agentDO.getAgentName() + randomStr);
        newAgentDO.setAgentDesc(agentDO.getAgentDesc());
        newAgentDO.setAiModelId(agentDO.getAiModelId());
        newAgentDO.setAiModelName(agentDO.getAiModelName());
        newAgentDO.setAiSysPromptText(agentDO.getAiSysPromptText());
        newAgentDO.setUpdateTime(LocalDateTime.now());
        newAgentDO.setCreateTime(LocalDateTime.now());
        newAgentDO.setWelcomeMsg(agentDO.getWelcomeMsg());
        newAgentDO.setIsLocked(agentDO.getIsLocked());
        agentMapper.insert(newAgentDO);

        // 发布信息也要复制一份
        List<AgentPublishConfigDO> configDOS = agentPublishConfigMapper.selectList(new LambdaQueryWrapper<AgentPublishConfigDO>()
                .eq(AgentPublishConfigDO::getAgentId, agentDO.getId())
                .eq(AgentPublishConfigDO::getAgentCode, agentDO.getAgentCode())
        );
        if (!CollectionUtils.isEmpty(configDOS)) {
            for (AgentPublishConfigDO configDO : configDOS) {
                AgentPublishConfigDO newConfigDO = new AgentPublishConfigDO();
                BeanUtils.copyProperties(configDO, newConfigDO);
                // 清除ID，插入新记录
                newConfigDO.setId(null);
                newConfigDO.setAgentId(newAgentDO.getId());
                newConfigDO.setAgentCode(newAgentDO.getAgentCode());
                newConfigDO.setPublishUrl(PublishTypeEnum.fromCode(newConfigDO.getPublishType()).getUrlPrefix() + newAgentDO.getAgentCode());
                newConfigDO.setUpdateTime(LocalDateTime.now());
                newConfigDO.setCreateTime(LocalDateTime.now());
                agentPublishConfigMapper.insert(newConfigDO);
            }
        }
        return ResponseResult.success();
    }

    @Override
    public ResponseResult<Void> updateAgentShowTitle(AgentPublishConfigParam param) {
        if (param == null || param.getId() == null || ObjectUtils.isEmpty(param.getAgentShowTitle())) {
            return ResponseResult.fail(1001, "参数错误");
        }
        AgentPublishConfigDO agentPublishConfigDO = agentPublishConfigMapper.selectById(param.getId());
        if (agentPublishConfigDO == null) {
            return ResponseResult.fail(1001, "发布配置不存在");
        }
        AgentDO agentDO = agentMapper.selectById(agentPublishConfigDO.getAgentId());
        if (agentDO == null) {
            return ResponseResult.fail(1001, "机器人不存在");
        }
        // 智能体被锁定
        if (agentDO.getIsLocked() != null && agentDO.getIsLocked() == 1) {
            return ResponseResult.fail(1001, "机器人被锁定，无法更新发布状态，请先解锁");
        }
        // 配置一样不做修改
        if (StringUtils.equals(agentPublishConfigDO.getAgentShowTitle(), param.getAgentShowTitle())) {
            return ResponseResult.success();
        }
        // 更新
        agentPublishConfigDO.setAgentShowTitle(param.getAgentShowTitle());
        agentPublishConfigDO.setUpdateTime(LocalDateTime.now());
        agentPublishConfigMapper.updateById(agentPublishConfigDO);
        return ResponseResult.success();
    }


}
